﻿using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace OfficeMiddlewareCore
{
    public class HttpHelper
    {
        private readonly HttpClient _httpClient;
        private HttpHelper()
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            ServicePointManager.ServerCertificateValidationCallback += (a, b, c, d) => true;
            _httpClient = new HttpClient();
        }
        private static HttpHelper _httpHelper;
        public static HttpHelper Instance
        {
            get
            {
                if (_httpHelper == null)
                {
                    _httpHelper = new HttpHelper();
                }
                return _httpHelper;
            }
        }

        /// <summary>
        /// 通知服务器，本地发生备份
        /// </summary>
        public void NotificationBackup(string url, string sessionId)
        {
            var uri = new Uri(url);

            _httpClient.DefaultRequestHeaders.Remove("Authentication");
            _httpClient.DefaultRequestHeaders.Add("Authentication", $"JSESSIONID={sessionId}");

            HttpResponseMessage response = null;

            response = AsyncHelper.RunSync(() => _httpClient.GetAsync(uri));
            response.EnsureSuccessStatusCode();

        }



        public void Download(string url, string filePath, string sessionId)
        {
            var uri = new Uri(url);
            var directory = Path.GetDirectoryName(filePath);
            if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);

            _httpClient.DefaultRequestHeaders.Remove("Authentication");
            _httpClient.DefaultRequestHeaders.Add("Authentication", $"JSESSIONID={sessionId}");

            HttpResponseMessage response = null;

            response = AsyncHelper.RunSync(() => _httpClient.GetAsync(uri));

            //WebSocketResponse.Create(CoreResponseStatus.网络异常, docCode);
            //LogHelper.Error(ex.Message, ex);
            //throw new CoreException(CoreResponseStatus.请求下载文件失败, docCode, ex.Message);

            response.EnsureSuccessStatusCode();

            using (var fs = File.Create(filePath))
            {
                var stream = response.Content.ReadAsStreamAsync().Result;
                stream.CopyTo(fs);
                fs.Flush();
            }

            //WebSocketResponse.Create(CoreResponseStatus.服务器内部异常, docCode, response.StatusCode.ToString());

            //LogHelper.Error($"请求下载文件失败{url},{response.StatusCode},{docCode}");
            //throw new CoreException(CoreResponseStatus.请求下载文件失败, docCode, ((int)response.StatusCode).ToString());

        }

        public bool Upload(string file, WsDto dto)
        {
            try
            {
                using (var formContent = new MultipartFormDataContent())
                {

                    _httpClient.DefaultRequestHeaders.Remove("Authentication");
                    _httpClient.DefaultRequestHeaders.Add("Authentication", $"JSESSIONID={dto.SessionId}");
                    var fileStreamContent = new StreamContent(File.OpenRead(file));
                    //formContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
                    formContent.Add(fileStreamContent, name: dto.DocCode, file);

                    var response = _httpClient.PostAsync(dto.UploadPath + "?fileVersion=" + (dto.FileVersion + 1), formContent).Result;
                    response.EnsureSuccessStatusCode();
                }
                return true;
            }
            catch (Exception ex)
            {
                //WebSocketResponse.Create(CoreResponseStatus.上传文件失败, dto);

                LogHelper.Error("上传文件失败", ex);

                return false;
            }
        }
    }

    internal static class AsyncHelper
    {
        private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None,
            TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);

        public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        {
            var cultureUi = CultureInfo.CurrentUICulture;
            var culture = CultureInfo.CurrentCulture;
            return _myTaskFactory.StartNew(() =>
            {
                Thread.CurrentThread.CurrentCulture = culture;
                Thread.CurrentThread.CurrentUICulture = cultureUi;
                return func();
            }).Unwrap().GetAwaiter().GetResult();
        }

        public static void RunSync(Func<Task> func)
        {
            var cultureUi = CultureInfo.CurrentUICulture;
            var culture = CultureInfo.CurrentCulture;
            _myTaskFactory.StartNew(() =>
            {
                Thread.CurrentThread.CurrentCulture = culture;
                Thread.CurrentThread.CurrentUICulture = cultureUi;
                return func();
            }).Unwrap().GetAwaiter().GetResult();
        }
    }
}
